package com.luo.d3s.ext.event.jdbc.receive;

import com.luo.d3s.core.domain.event.DomainEvent;
import com.luo.d3s.core.domain.event.DomainEventRecordRepository;
import org.aspectj.lang.ProceedingJoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 领域事件处理器 - 消息消费幂等、事务管理 - 实现
 *
 * @author luohq
 * @date 2023-02-01 16:41
 */

@Component
public class DomainEventIdempotentTxHandler {

    private static final Logger log = LoggerFactory.getLogger(DomainEventIdempotentTxHandler.class);

    @Resource
    private DomainEventRecordRepository domainEventRecordRepository;

    /**
     * 此处需保证 事件接收记录入库 和 业务DB处理操作 在同一个事务中，
     * 即此处的@Transactional嵌套连接点的@Transactional处理。
     *
     * @param joinPoint
     * @throws Throwable
     */
    @Transactional(rollbackFor = Throwable.class)
    public void proceedWithTx(ProceedingJoinPoint joinPoint) throws Throwable {
        DomainEvent domainEvent = (DomainEvent) joinPoint.getArgs()[0];
        //消息消费幂等处理
        Boolean recordSuccess = this.domainEventRecordRepository.record(domainEvent);
        log.debug("Domain Event Idempotent Record: {}", recordSuccess);
        //记录成功，则不重复可消费
        if (recordSuccess) {
            joinPoint.proceed();
        }
    }
}
